/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * dlgIngresoOptimoProductos.java
 *
 * Created on 09/11/2011, 06:31:31 PM
 */

package visual.Ingreso;

import bentity.beCoordenada;
import bentity.beEntrada;
import bentity.beIngreso;
import bentity.beLote;
import bentity.bePallet;
import bentity.beProducto;
import bentity.beUbicacion;
import bentity.beUsuario;
import blogic.blAlmacen;
import blogic.blHelper;
import blogic.blIngreso;
import blogic.blLog;
import blogic.blLote;
import blogic.blOrdenDespacho;
import blogic.blPallet;
import blogic.blProducto;
import blogic.blUbicacion;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import javax.swing.table.DefaultTableModel;
import visual.Seguridad.visualHelper;

/**
 *
 * @author giulio
 */
public class dlgIngresoOptimoProductos extends javax.swing.JDialog {
    private ArrayList<beLote> arrLotes=new ArrayList<beLote>();
    private ArrayList<beEntrada> entradas = new ArrayList<beEntrada>();
    private DefaultTableModel dtm = null;
    beUsuario usuario=null;


    /** Creates new form dlgIngresoOptimoProductos */
    public dlgIngresoOptimoProductos(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        initComponents();
    }

    public dlgIngresoOptimoProductos(pnfUbicacionPallet parent, boolean modal, ArrayList<beLote> arrLotes,beUsuario usuario){
        super((java.awt.Frame) null, modal);
        initComponents();
        this.setBounds(0, 0, 750, 550);
        visualHelper.centrarDialogoEnPantalla(this);
        try{

            this.usuario=usuario;

            //

            this.arrLotes = arrLotes;

            //

            this.entradas = (new blAlmacen()).buscarObjsEntrada();

            this.dtm=(DefaultTableModel)this.tblIngresoProductos.getModel();

            if (this.algoritmo()){
                visualHelper.mostrarMensajeSatisfaccion("Se ejecutó el algoritmo satisfactoriamente");
                this.llenarTabla();
            }
            else{
                visualHelper.mostrarMensajeAdvertencia("No hay suficientes ubicaciones que cumplan con los requisitos de los pallets");
                this.btnRegistraIngreso.setEnabled(false);
                this.btnVerMapa.setEnabled(false);
                this.setVisible(false);
                this.dispose();
                return;
            }
        }
        catch(Exception e){
            e.printStackTrace();
            visualHelper.mostrarMensajeError("Ocurrió un error durante la ejecución del algoritmo de selección.");
        }
    }

    private void asignarIdLoteAPallet(){
        int idLote = -1;
        for(int i=0; i<this.arrLotes.size();i++){
            for(int j=0;j<this.arrLotes.get(i).getPallets().size();j++){
                idLote = this.arrLotes.get(i).getIdLote();
                this.arrLotes.get(i).getPallets().get(j).setId_lote(idLote);
            }
        }
    }

    private void llenarTabla() throws Exception{
        
        Object [] datos = new Object [6];
        int idLote = -1;
        ArrayList<bePallet> palletAux = null;
        int indice=0;
        Date fecha;



        for(int i=0;i<=this.dtm.getRowCount()-1;){
            this.dtm.removeRow(0);
        }

        Calendar calendario=Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");

        for(int i=0;i<this.arrLotes.size();i++){
            palletAux = this.arrLotes.get(i).getPallets();
            idLote = this.arrLotes.get(i).getIdLote();
            fecha=this.arrLotes.get(i).getFechaVencimiento();
            for(int j=0;j<palletAux.size();j++){
                datos[0] = indice+1;
                datos[1] = idLote;
                datos[2] = palletAux.get(j).getNroPallet();
                datos[3] = new blProducto().obtenerProductoPorCodigo(palletAux.get(j).getUbicacion().getIdProducto()).getNombre();
                datos[4] = sdf.format(fecha);
                datos[5] = palletAux.get(j).getUbicacion().getCoordenadas().obtenerStringCoordenadas();
                this.dtm.addRow(datos);
                indice++;
            }
        }
        this.tblIngresoProductos.setRowSelectionAllowed(true);
        this.tblIngresoProductos.setColumnSelectionAllowed(false);
    }

    private boolean algoritmo() throws Exception{
        int xEnt=-1;
        int yEnt=-1;
        blUbicacion blu=new blUbicacion();
        ArrayList<Integer> utilisimas=new ArrayList<Integer>(); //Ubicaciones ya utilizadas
        beUbicacion leBestUbic = null;
        ArrayList<beUbicacion> arrUbicsCandidatas=new ArrayList<beUbicacion>();
        beCoordenada coord1 = null;
        beCoordenada coord2 = null;
        double distancia1 = -1.0;
        double distancia2 = -1.0;

            ordenarLotesYPallets();

            //ITERACION DE LOTES
            for(int i=0;i<this.arrLotes.size();i++){

                beProducto prod=(new blProducto()).obtenerProductoPorCodigo(arrLotes.get(i).getIdProducto());

                arrUbicsCandidatas=blu.dameUbicacionesPosibles(prod.getTipoProducto(), this.arrLotes.get(i).getPallets().get(0).getTipo_pallet());

                //ITERACION DE PALLETS
                for(int j=0;j<this.arrLotes.get(i).getCantidadPallets();j++){


                    //arrUbicsCandidatas=blu.dameUbicacionesPosibles(prod.getTipoProducto(),arrLotes.get(i).getPallets().get(j).getTipo_pallet());

                    arrUbicsCandidatas=separarUtilizadasDeLasNuevas(arrUbicsCandidatas,utilisimas);

                    leBestUbic=null;

                    for(int k=0;k<arrUbicsCandidatas.size();k++){

                        //ITERACION DE ENTRADAS
                        for(int m=0;m<this.entradas.size();m++){
                            xEnt=((beEntrada)entradas.get(m)).getPos_x();
                            yEnt=((beEntrada)entradas.get(m)).getPos_y();

                            if(leBestUbic==null)
                                leBestUbic=arrUbicsCandidatas.get(k);
                            else{
                                coord1=leBestUbic.getCoordenadas(); //MejorUbicacion
                                coord2=arrUbicsCandidatas.get(k).getCoordenadas(); //UbicacionCandidata

                                distancia1=dameDistancia(coord1.getxEnMapa(),coord1.getyEnMapa(),xEnt,yEnt); //MejorDistancia
                                distancia2=dameDistancia(coord2.getxEnMapa(),coord2.getyEnMapa(),xEnt,yEnt); //DistanciaCandidata

                                if(distancia2>distancia1){ //Candidata: mas cerca.
                                    if(coord2.getPiso()<coord1.getPiso()){ //Candidata: mas cerca, piso menor
                                        leBestUbic=arrUbicsCandidatas.get(k);
                                    }
                                    else{  //Candidata: mas cerca, piso mayor
                                        if(leBestUbic.getId_rack()!=arrUbicsCandidatas.get(k).getId_rack()){ //Candidata: mas cerca, piso mayor, distinto rack
                                            leBestUbic=arrUbicsCandidatas.get(k);
                                        }
                                    }
                                }
                                else{ //Candidata: mas lejos
                                    if(coord2.getPiso()<coord1.getPiso() && leBestUbic.getId_rack()==arrUbicsCandidatas.get(k).getId_rack()){
                                        //Candidata: mas lejos, piso menor, mismo rack
                                        leBestUbic=arrUbicsCandidatas.get(k);
                                    }
                                }

                            }

                        }

                    }

                    if(leBestUbic==null){
                        return false;
                    }


                    beProducto pd=(new blProducto().obtenerProductoPorCodigo(this.arrLotes.get(i).getIdProducto()));

                    leBestUbic.setIdProducto(pd.getIdProducto());
                    leBestUbic.setTipoProd(pd.getTipoProducto());
                    leBestUbic.setIdPallet(this.arrLotes.get(i).getPallets().get(j).getId_Pallet());
                    leBestUbic.setTipo_pallet(this.arrLotes.get(i).getPallets().get(j).getTipo_pallet());
                    leBestUbic.setFechaVencimiento(this.arrLotes.get(i).getFechaVencimiento());

                    this.arrLotes.get(i).getPallets().get(j).setUbicacion(leBestUbic);
                    utilisimas.add(leBestUbic.getId_ubicacion());
                    arrUbicsCandidatas.remove(leBestUbic);
                }

            }       

        return true;


    }

    private void ordenarLotesYPallets() throws Exception{
        ArrayList<beLote> copyLotes=new ArrayList<beLote>();
        blOrdenDespacho blod= new blOrdenDespacho();
        int indiceTotal=0;
        int indiceParcial=0;
//        Calendar calendario=Calendar.getInstance();
//        calendario.set(0,1, 1);

        int cantidadMax=0;
        int cantidadVendidas=-1;

        Date fechaMin=new Date(Long.MAX_VALUE);
        fechaMin=(blHelper.setTimeToMidnight(fechaMin));
        Date fechaProd;


       
            while(!arrLotes.isEmpty()){
                indiceTotal=0;

                cantidadMax=-1;
                fechaMin=new Date(Long.MAX_VALUE);

                for(int i=0;i<arrLotes.size();i++){

                    cantidadVendidas=blod.obtenerNumeroDespachoProducto(arrLotes.get(i).getIdProducto(), 1);
                    fechaProd=this.arrLotes.get(i).getFechaVencimiento();
                    fechaProd=(blHelper.setTimeToMidnight(fechaProd));

                    indiceParcial=this.arrLotes.get(i).getCantidadPallets();

                    
                    if(fechaProd.before(fechaMin)){
                        fechaMin=fechaProd;
                        cantidadMax=cantidadVendidas;

                        copyLotes.add(arrLotes.get(i));
                        arrLotes.remove(i);

                        break;
                    }
                    else if(fechaProd.equals(fechaProd)){
                        if(cantidadVendidas>cantidadMax){
                            cantidadMax=cantidadVendidas;

                            copyLotes.add(arrLotes.get(i));
                            arrLotes.remove(i);
                            break;
                        }
                    }
                    
                    indiceTotal+=indiceParcial;
                }
            }
            this.arrLotes=copyLotes;
    }

    private double dameDistancia(int x1,int y1,int x2, int y2){
        return Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2));
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        lblTitulo = new javax.swing.JLabel();
        jScrollPane5 = new javax.swing.JScrollPane();
        tblIngresoProductos = new javax.swing.JTable();
        btnRegistraIngreso = new javax.swing.JButton();
        btnVerMapa = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setAlwaysOnTop(true);
        setMinimumSize(new java.awt.Dimension(750, 550));
        setModal(true);
        setResizable(false);
        getContentPane().setLayout(null);

        lblTitulo.setFont(new java.awt.Font("DejaVu Sans", 0, 36));
        lblTitulo.setForeground(new java.awt.Color(0, 0, 0));
        lblTitulo.setText("Ingreso de productos");
        getContentPane().add(lblTitulo);
        lblTitulo.setBounds(190, 20, 390, 43);

        tblIngresoProductos.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "N°", "Lote", "Pallet", "Producto", "Vencimiento", "Coordenadas"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.Integer.class, java.lang.Integer.class, java.lang.Integer.class, java.lang.String.class, java.lang.Object.class, java.lang.String.class
            };
            boolean[] canEdit = new boolean [] {
                false, false, false, false, false, false
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        tblIngresoProductos.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        tblIngresoProductos.getTableHeader().setReorderingAllowed(false);
        jScrollPane5.setViewportView(tblIngresoProductos);
        tblIngresoProductos.getColumnModel().getColumn(0).setPreferredWidth(30);

        getContentPane().add(jScrollPane5);
        jScrollPane5.setBounds(30, 80, 690, 360);

        btnRegistraIngreso.setBackground(new java.awt.Color(240, 235, 226));
        btnRegistraIngreso.setFont(new java.awt.Font("Dialog", 0, 12));
        btnRegistraIngreso.setForeground(new java.awt.Color(0, 0, 0));
        btnRegistraIngreso.setText("Registrar ingreso");
        btnRegistraIngreso.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnRegistraIngresoActionPerformed(evt);
            }
        });
        getContentPane().add(btnRegistraIngreso);
        btnRegistraIngreso.setBounds(210, 460, 150, 27);

        btnVerMapa.setBackground(new java.awt.Color(240, 235, 226));
        btnVerMapa.setFont(new java.awt.Font("Dialog", 0, 12));
        btnVerMapa.setForeground(new java.awt.Color(0, 0, 0));
        btnVerMapa.setText("Reubicación manual");
        btnVerMapa.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnVerMapaActionPerformed(evt);
            }
        });
        getContentPane().add(btnVerMapa);
        btnVerMapa.setBounds(380, 460, 160, 27);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void btnRegistraIngresoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRegistraIngresoActionPerformed
        // TODO add your handling code here:
        ArrayList<bePallet> arrPallets =new ArrayList<bePallet>();
        int stockGood=0;

        try{

            //

            int idIngreso=(new blIngreso().registrarIngreso());

            for(int i=0;i<this.arrLotes.size();i++){
                this.arrLotes.get(i).setIdIngreso(idIngreso);
            }

            this.arrLotes = (new blLote()).registrarLotes(this.arrLotes);

            int rLog=-1;
            for(int i=0;i<this.arrLotes.size();i++){
                rLog=(new blLog().registrarLog(usuario.getIdUsuario(), usuario.getCargo(), "Se registró el lote "+arrLotes.get(i).getIdLote()+" perteneciente al ingreso "+idIngreso));
            }

            //

            this.asignarIdLoteAPallet();
            (new blPallet()).registrarLotes(this.arrLotes);

            for(int i=0;i<this.arrLotes.size();i++){
                arrPallets=this.arrLotes.get(i).getPallets();
                stockGood=(new blProducto().actualizarStockAgregado(arrPallets));
                for(int j=0;j<arrPallets.size();j++){
                    rLog=(new blLog().registrarLog(usuario.getIdUsuario(), usuario.getCargo(), "Se registró el pallet con código "+arrPallets.get(j).getId_Pallet()+", perteneciente al lote con código "+arrLotes.get(i).getIdLote()+", con "+arrLotes.get(i).getCajasPorPallet()+" cajas, en la ubicacion con coordenadas "+arrPallets.get(j).getUbicacion().getCoordenadas().obtenerStringCoordenadas()));
                }
            }

            (new blUbicacion()).registrarIngresoPallets(this.arrLotes);

            for(int i=0;i<this.arrLotes.size();i++){
                arrPallets=this.arrLotes.get(i).getPallets();
                stockGood=(new blProducto().actualizarStockAgregado(arrPallets));
            }

            visualHelper.mostrarMensajeSatisfaccion("Se ingresaron satisfactoriamente los pallets.");
            this.btnRegistraIngreso.setEnabled(false);

            this.setVisible(false);
            this.dispose();
        }
        catch(Exception e){
            e.printStackTrace();
            visualHelper.mostrarMensajeError("Ocurrió un error al registrar los pallets.");
        }
}//GEN-LAST:event_btnRegistraIngresoActionPerformed

    private void btnVerMapaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnVerMapaActionPerformed
        dlgMostrarIngreso min=new dlgMostrarIngreso(null,true,arrLotes);
        min.setVisible(true);

        try{

        if(min.getSeDebeGuardar()){
            this.arrLotes=min.getArrLotes();

            for(int i=0;i<=this.dtm.getRowCount()-1;){
                this.dtm.removeRow(0);
            }

            this.llenarTabla();

        }

        }catch(Exception e){
            e.printStackTrace();
            visualHelper.mostrarMensajeError("Ocurrió un error");
        }
    }//GEN-LAST:event_btnVerMapaActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnRegistraIngreso;
    private javax.swing.JButton btnVerMapa;
    private javax.swing.JScrollPane jScrollPane5;
    private javax.swing.JLabel lblTitulo;
    private javax.swing.JTable tblIngresoProductos;
    // End of variables declaration//GEN-END:variables

    private ArrayList<beUbicacion> separarUtilizadasDeLasNuevas(ArrayList<beUbicacion> arrUbicsCandidatas, ArrayList<Integer> utilisimas){
        ArrayList<beUbicacion> candidatasActualizadas=new ArrayList<beUbicacion>();

        if(utilisimas.size()==0) return arrUbicsCandidatas;

        for(int i=0;i<arrUbicsCandidatas.size();i++){
            for(int j=0;j<utilisimas.size();j++){
                if(arrUbicsCandidatas.get(i).getId_ubicacion()==utilisimas.get(j)){
                    break;
                }
                if(j==(utilisimas.size()-1)){
                    candidatasActualizadas.add(arrUbicsCandidatas.get(i));
                }
            }
        }

        return candidatasActualizadas;
    }

    

}
